package imoney.shared.model;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;

import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;

/**
 * A money transaction is an object used to model and make persistent 
 * every entry in the interface. It's linked uniquely to a user with no
 * explicit notion of group belonging. Concretely : when a user records
 * a new expense, all the informations he enters are instanciated in a transaction
 * which will be used to update every concerned member of his group, and will
 * then be stored for future reference (consistancy check, or in case of a desagreement)
 * 
 * @author Arnaud PELOQUIN
 *
 */
@PersistenceCapable
public class MoneyTransaction extends Registreable implements Serializable {

	/**
	 * The date of the last incompatible updates (fields changes,
	 * methods changes).
	 */
	private static final long serialVersionUID = 23082010L;
	@Persistent
	private double amount;
	@Persistent
	private String header;
	@Persistent
	private int payer;
	@Persistent
	private ArrayList<Integer> beneficiaries;
	@Persistent
	private ArrayList<Double> repartition;
	@Persistent
	private Date date;

	/**
	 * Manual-repartition constructor. Use only when the amounts are set manually by the user
	 * (which is to say when the amounts are not equally distributed between members).
	 * @param transacAmount
	 * @param head : a description of the event
	 * @param payer : the list of payers
	 * @param beneficiary
	 * @param repart : the money repartition. Must be positive numbers (debt manager then puts a minus sign when necessary)
	 * @throws Exception 
	 */
	public MoneyTransaction(double transacAmount, String head, int thePayer, ArrayList<Integer> beneficiary,
			ArrayList<Double> repart) throws Exception{
		try{
			for(double partialAmount : repart){
				if(partialAmount<0){
					throw new Exception("Repartition must contain positive doubles only");
				}
			}
		}catch(NullPointerException nEx){}
		amount = transacAmount;
		header = head;
		payer = thePayer;
		beneficiaries = beneficiary;
		// TODO : check if Sum of 'repartition' = 'amount', and maybe consider the payer as beneficiary of remaining
		// amount ?
		repartition = repart;
		date = new Date();
	}


	/**
	 * Auto-repartition constructor. Remark : this implementation will always consider the payer out of the beneficiaries.
	 * This means that if the payer has also beneficied from the payement, it must be added to the list of beneficiaries
	 * as any other.
	 * @param transacAmount
	 * @param head : a description of the event
	 * @param payer : the payer
	 * @param beneficiary
	 * @throws Exception 
	 */
	public MoneyTransaction(double transacAmount, String head, int payer, ArrayList<Integer> beneficiary) throws Exception{
		this(transacAmount, head,payer,beneficiary,null);
		autoRepartition(transacAmount, beneficiary.size());
	}

	/**
	 * Empty constructor for Potential Serialization
	 */
	public MoneyTransaction(){
		// TODO : check if such an empty constructor is ok
	}

	// GETTERS ----------------------------------------------
	
	public double getAmount(){
		return amount;
	}
	public String getHeader(){
		return header;
	}
	public int getPayer(){
		return payer;
	}
	public ArrayList<Integer> getBeneficiaries(){
		return beneficiaries;
	}
	public ArrayList<Double> getRepartition(){
		return repartition;
	}
	@SuppressWarnings("deprecation")
	public String getDate(){
		return date.toGMTString();
	}

	@Override
	public String getAvailabilityQuery() {
		//TODO : ajouter la date (sans que ça bug sur le parsing) dans les critères d'unicité
		return "select from "+MoneyTransaction.class.getName()+" where header =='"+header+"' && amount == '"+getAmount()+"'";
		//amount =='"+amount+"' &&
	}

	@Override
	public String getAvailabilityExceptionMessage() {
		return "Une transaction d'un montant de :"+amount+", intitulee '"+header+"' a déjà été enregistrée le "+date;
	}

	private void autoRepartition(double transacAmount, int benefNumber){
		repartition = new ArrayList<Double>();
		for(int i=0; i<benefNumber; i++){
			repartition.add(transacAmount/benefNumber);
		}
	}
	public String toString(){
		return "ID: "+getId()+",   amount: "+getAmount()+",   header: " +getHeader()+ ",   payer: "+getPayer()
		+",   date :"+getDate()+",   all for now";
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}
